package control;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import survey.Synchronizer;
import survey.PictureDisplayer;
import cameracontrol.CameraController;
import cameracontrol.DatagramPictureCollector;
import control.ExitControl;
import cameracontrol.MotionController;
import cameracontrol.MotionThread;

import gui.Frame;

public class ConnectionManager {
	private String[] inOne;
	private String[] inTwo;
	private Frame gui;
	private CameraController cc = null;
	private CameraController cc2 = null;
	private MotionThread mt = null;
	private MotionThread mt2 = null;
	private MotionController mc;
	private PictureDisplayer sy;
	private Synchronizer sc;
	private DatagramPictureCollector dpc;
	private ArrayList<CameraController> list;

	/**
	 * Creates a configuration control.
	 * 
	 * @param inOne
	 *            String[] with size = 3 that includes necessary input for
	 *            camera one.
	 * @param inTwo
	 *            String[] with size = 3 that includes necessary input for
	 *            camera two.
	 * @param gui
	 *            Configuration GUI
	 */
	public ConnectionManager(String[] inOne, String[] inTwo, Frame gui) {
		this.inOne = inOne;
		this.inTwo = inTwo;
		this.gui = gui;
		new ForcedMotion(this, gui.getCameraPanel());
		new ForcedSync(this, gui.getCameraPanel());
		new ExitControl(gui.getCameraPanel());
		gui.getConnectionPanel().addConnectListener(new ConnectionListener());
	}
	/**
	 * Initiates the systems threads.
	 */
	private void initiateThreads() {
		sc = new Synchronizer();
		sy = new PictureDisplayer(gui.getCameraPanel(), sc);
		dpc = new DatagramPictureCollector(8000, sc);
		
	}
	
	public MotionController getMotionController(){
		return mc;
	}
	public Synchronizer getSurveyController() {
		return sc;
	}


	public class ConnectionListener implements ActionListener {

		public void actionPerformed(ActionEvent arg0) {
			if (!gui.getConnectionPanel().connected()) {
				gui.getConnectionPanel().getTextValues(inOne, inTwo);
				if(!setUpCameras()){
					return;
				}
				
				list = new ArrayList<CameraController>();
				list.add(cc);
				list.add(cc2);
				mc = new MotionController(list, gui.getCameraPanel());				
				if(!setUpMotionDetectors()){
					return;
				}				
				initiateThreads();
				startThreads();
				gui.getConnectionPanel().setDisconnect();
				gui.getConnectionPanel().setVisible(false);
				gui.getCameraPanel().setVisible(true);		
				gui.pack();
			}else {
				tearDownThreads();						
				gui.getConnectionPanel().setConnect();
				gui.getCameraPanel().setVisible(false);
				gui.getCameraPanel().reset();
				gui.pack();
			}
		}

		/**
		 * Starts all threads in the system.
		 */
		private void startThreads() {
			sy.start();
			dpc.start();
			cc.start();
			cc2.start();
			mc.start();
			mt.start();
			mt2.start();
		}

		/**
		 * setups the motiondetectors according to input.
		 */
		private boolean setUpMotionDetectors() {
			try {
				mt = new MotionThread(mc, inOne[0], Integer.parseInt(inOne[2]));
			} catch (NumberFormatException e) {
				System.out
						.println("Motion detection one couldn't be initiated, check your motion port numbers!");
				return false; 
			} catch (UnknownHostException e) {
				System.out
						.println("Couldn't identify host, make sure the server is up "
								+ "and running and check that you have entered the correct adress");
				return false;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				mt2 = new MotionThread(mc, inTwo[0], Integer.parseInt(inTwo[2]));
			} catch (NumberFormatException e) {
				System.out
						.println("Motion detection one couldn't be initiated, check your motion port numbers!");
				return false;
			} catch (UnknownHostException e) {
				System.out
						.println("Couldn't identify host, make sure the server is up "
								+ "and running and check that you have entered the correct adress");
				return false;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return true;
		}
		/**
		 * setups the camera controllers according to input.
		 */
		private boolean setUpCameras() {
			try {
				cc = new CameraController(5000, inOne[0], Integer
						.parseInt(inOne[1]));
			} catch (NumberFormatException e) {
				System.out
						.println("Camera one couldn't be initiated, check your port numbers!");
				return false;
			} catch (NullPointerException e) {
				System.out
						.println("You missed to fill in addreses on camera one");
				return false;
			} catch (UnknownHostException e) {
				System.out
						.println("Couldn't identify host, make sure the server is up "
								+ "and running and check that you have entered the correct adress");
				return false;
			} catch (IOException e) {
				System.out.println("Couldn't identify host, make sure the server is up "
						+ "and running and check that you have entered the correct adress");
				return false;
			}

			try {
				cc2 = new CameraController(5000, inTwo[0], Integer
						.parseInt(inTwo[1]));			
			} catch (NumberFormatException e) {
				System.out
						.println("Camera two couldn't be initiated, check your port numbers!");
				return false;
			} catch (NullPointerException e) {
				System.out
						.println("You missed to fill in addreses on camera two");
				return false;
			} catch (UnknownHostException e) {
				System.out
						.println("Couldn't identify host, make sure the server is up "
								+ "and running and check that you have entered the correct address");
				return false;
			} catch (IOException e) {
				System.out.println("Couldn't identify host, make sure the server is up "
						+ "and running and check that you have entered the correct adress");
				return false;
			}
			return true;
		}
		
		private void tearDownThreads() {
			mt.kill();
			mt2.kill();
			mc.kill();
			cc.kill();
			cc2.kill();
			dpc.kill();
			sy.kill();		
			mt = null;
			mt2 = null;
			mc = null;
			cc = null;
			cc2 = null;
			dpc = null;
			sy = null;
		}

	}


}